home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Printer Drivers… / ImageWriterLQ (alt. rdip) / OldAPIMessageIntf.c < prev    next >
Encoding:
Text File  |  1996-06-15  |  19.6 KB  |  716 lines  |  [TEXT/MPS ]

  1. /*---------------------------------------------------------------------------
  2. FILENAME
  3.     OldAPIMessageIntf.c
  4.  
  5. DESCRIPTION
  6.     This module contains the routines which implement the old API messages
  7.     that the ImageWriter LQ driver overrides.  Much of the logic in this
  8.     module was gleaned from the original ImageWriter LQ driver, and so
  9.     some of the calculations may seem a little strange.  In order to maintain
  10.     compatibility with the old driver's logic, we must preserve much of the
  11.     old logic.
  12.         
  13. COPYRIGHT
  14.      Copyright Apple Computer, Inc. 1992-1996
  15.      All rights reserved. 
  16.         
  17. INTERFACE ROUTINES:
  18.  
  19.     SD_PrValidate
  20.     SD_ConvertPrintRecordTo
  21.     SD_ConvertPrintRecordFrom
  22.  
  23.     12/20/93 - dmh - Sync'd with the shipping 1.0b3 GX driver.
  24.      8/28/94 - dmh - Sync'd with the shipping 1.0.1 GX driver.
  25.      6/14/96 - cn  - Updated to support Universal Interfaces 2.1.
  26.  
  27. -------------------------------------------------------------------------------- */
  28.  
  29. // Include the standard Mac header files 
  30. #include "MacIncludes.h"
  31.  
  32. // Include the new QuickDraw GX graphics header files 
  33. #include <GXGraphics.h>
  34. #include <GraphicsLibraries.h>
  35. #include <GXMath.h>
  36.  
  37. // Include the required Printing Manager header files 
  38. #include <GXPrinting.h>
  39. #include <GXPrinterDrivers.h>
  40. #include <Collections.h>
  41. #include <GXMessages.h>
  42. #include <GXExceptions.h>
  43.  
  44. // Include the internal driver constants and types used by this module 
  45. #include "LQResources.h"
  46. #include "OldAPIMessageIntf.h"
  47.  
  48.  
  49. /***************************************************************************************
  50. *                                         INTERNAL ROUTINES                                                    *
  51. ***************************************************************************************/
  52.  
  53.  
  54. /****************************************************************************************
  55.  
  56.                             OldLQ_CiMetrics
  57.                             
  58.     function:
  59.                 This function takes an old style print record and massages its fields in 
  60.                 a manner equivalent to the old style LQ driver.  This logic is basically
  61.                 lifted from the old LQ driver.
  62.                 
  63.     parameters:                
  64.                 hPrint        target print record whose fields are to be updated
  65.  
  66.     returns:
  67.                 none
  68.     
  69. ****************************************************************************************/
  70. void OldLQ_CiMetrics(THPrint    hPrint)
  71. {
  72.     TPPrint    pPrint = *hPrint;
  73.     short        dhPage;
  74.     short        dvPage;
  75.     short        dhPaper;
  76.     short        dvPaper;
  77.     short        hOff;
  78.     short        vOff;
  79.     short        cPlaten;
  80.     short        gap;
  81.     short        scanBits;
  82.     short        maxH;
  83.     short        wDev;
  84.  
  85.     cPlaten = kPlaten8;
  86.     if ( pPrint->prStl.iPageH > (9 * kMysticPaperFract) ) 
  87.     {
  88.         cPlaten = kPlaten15;                     // platen width in half inches
  89.     }
  90.  
  91.     wDev = pPrint->printX[1];
  92.     pPrint->prInfo.iDev = 0;                     // Use screen device for lo res or fake hi res
  93.     if ( !TestBit(wDev, kResSetBit) )         // not fResSet
  94.     {                                     
  95.         pPrint->prInfo.iVRes = 72;
  96.         pPrint->prInfo.iHRes = 72;
  97.     }                                         
  98.     else
  99.     if ( pPrint->prInfo.iVRes == 216 )    // Real HiRes
  100.     {
  101.         wDev |= kHighResBit;                    //    force "hi res"
  102.         wDev &= ~k66PercentReducBit;         // clear 66% Reduction off
  103.         wDev &= ~k33PercentReducBit;         // clear 33% Reduction off
  104.         pPrint->printX[1] = wDev;
  105.     }
  106.  
  107.     // Calculate rPaper height in Y
  108.     dvPaper = (pPrint->prStl.iPageV * pPrint->prInfo.iVRes) / kMysticPaperFract;
  109.     
  110.     // Calculate rPage height in Y
  111.     gap = (60 * pPrint->prInfo.iVRes) / kMysticPaperFract;
  112.             
  113.     if ( TestBit(wDev, kScrollBit) )
  114.     {
  115.         gap = 0;
  116.     }
  117.             
  118.     // force page height to be an integral number of head scans
  119.     dvPage = (( dvPaper - gap ) / 24) * 24;
  120.         
  121.     // Calculate rPaper width in dots
  122.     dhPaper = (pPrint->prStl.iPageH * pPrint->prInfo.iHRes) / kMysticPaperFract;
  123.  
  124.     // Calculate max width in dots
  125.         
  126.     maxH = ( cPlaten * pPrint->prInfo.iHRes ) >> 1;
  127.     if (maxH > dhPaper)
  128.     {
  129.         maxH = dhPaper;
  130.     }
  131.     scanBits = ( maxH >> 4 ) << 4;    // force to word boundary
  132.  
  133.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait orientation
  134.     {
  135.         dhPage = scanBits;
  136.     }
  137.     else    //    Landscape orientation: switch height and width
  138.     {
  139.         dhPage = dvPage;
  140.         dvPage = scanBits;
  141.     }
  142.  
  143.     SetRect(&pPrint->prInfo.rPage, 0, 0, dhPage, dvPage);
  144.  
  145.     // Calculate rPaper offsets, & set rPaper
  146.     
  147.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait orientation
  148.     {
  149.         hOff = (dhPage - dhPaper) >> 1; // Note: Negative
  150.         vOff = -gap;
  151.     }
  152.     else    //    Landscape orientation: switch height and width
  153.     {
  154.         short        iTemp;
  155.  
  156.         iTemp = dhPaper;
  157.         dhPaper = dvPaper;
  158.         dvPaper = iTemp;
  159.  
  160.         hOff = - gap;
  161.         vOff = (dvPage - dvPaper) >> 1;
  162.     }
  163.     SetRect(&pPrint->rPaper, hOff, vOff, dhPaper + hOff, dvPaper + vOff);
  164.         
  165.     // Calculate rPage height in dots, & set rPage
  166.     //If 66% reduction, triple both rectangles: ( Page and Paper )
  167.  
  168.     if ( TestBit(wDev, k66PercentReducBit) )    //    66% reduction selected
  169.     {
  170.         pPrint->prInfo.rPage.right *= 3;
  171.         pPrint->prInfo.rPage.bottom *= 3;
  172.         
  173.         pPrint->rPaper.top *= 3;
  174.         pPrint->rPaper.left *= 3;
  175.         pPrint->rPaper.right *= 3;
  176.         pPrint->rPaper.bottom *= 3;
  177.     }
  178.  
  179.     // If 33% reduction, scale both rectangles: ( Page and Paper )
  180.     if ( TestBit(wDev, k33PercentReducBit) )    //    33% reduction selected
  181.     {
  182.         pPrint->prInfo.rPage.right = FixRound( FixMul( lScale, (pPrint->prInfo.rPage.right << 16) ));
  183.         pPrint->prInfo.rPage.bottom = FixRound( FixMul( lScale, (pPrint->prInfo.rPage.bottom << 16) ));
  184.         
  185.         pPrint->rPaper.top = FixRound( FixMul( lScale, (pPrint->rPaper.top << 16) ));
  186.         pPrint->rPaper.left = FixRound( FixMul( lScale, (pPrint->rPaper.left << 16) ));
  187.         pPrint->rPaper.right = FixRound( FixMul( lScale, (pPrint->rPaper.right << 16) ));
  188.         pPrint->rPaper.bottom = FixRound( FixMul( lScale, (pPrint->rPaper.bottom << 16) ));
  189.     }
  190.                 
  191.     if ( TestBit(wDev, kDraftBit) )    //    Draft bits selected
  192.     {
  193.         pPrint->prJob.bJDocLoop = bDraftLoop;
  194.     }
  195.  
  196.     // Copy WDEV field back to old position for apps that read these flags
  197.     
  198.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )
  199.     {
  200.         wDev |= kPortraitBit;
  201.     }
  202.     else
  203.     {
  204.         wDev &= ~kPortraitBit;
  205.     }
  206.     
  207.     pPrint->printX[1] = wDev;
  208.     pPrint->prStl.wDev = wDev;
  209. }
  210. /* OldLQ_CiMetrics */
  211.  
  212.  
  213. /****************************************************************************************
  214.  
  215.                             OldLQ_CiXMetrics
  216.                             
  217.     function:
  218.                 This function takes an old style print record and massages the PrInfoPT and
  219.                 PrXInfo fields in a manner equivalent to the old style LQ driver.  This logic 
  220.                 is basically lifted from the old LQ driver.
  221.                 
  222.     parameters:                
  223.                 hPrint        target print record whose fields are to be updated
  224.  
  225.     returns:
  226.                 none
  227.     
  228. ****************************************************************************************/
  229. void OldLQ_CiXMetrics(THPrint    hPrint)
  230. {
  231.     TPPrint    pPrint = *hPrint;
  232.     short        iScans;
  233.     short        iDevExtra;
  234.  
  235.     pPrint->prInfoPT = pPrint->prInfo; // Start with a straight copy
  236.  
  237.     pPrint->prXInfo.bPatScale = 0;
  238.  
  239.     if ( !TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Landscape mode
  240.     {
  241.         pPrint->prJob.bJDocLoop = bSpoolLoop; // Force spooling for landscape
  242.     }
  243.  
  244.     if ( TestBit(pPrint->printX[1], k66PercentReducBit) || TestBit(pPrint->printX[1], k33PercentReducBit) ) // 33% or 66% reduction
  245.     {
  246.         pPrint->printX[1] &= ~kHighResBit;        //    Clear the high-res bit
  247.         
  248.         if ( TestBit(pPrint->printX[1], k33PercentReducBit) )    // If 33% Reduction ONLY
  249.         {
  250.             pPrint->prXInfo.bPatScale = 2;         // Pattern double
  251.             
  252.             // SCALE 2X FOR 33% REDUCTION CASE
  253.             pPrint->prInfoPT.rPage.right <<= 1;
  254.             pPrint->prInfoPT.rPage.bottom <<= 1;
  255.         }
  256.     }
  257.  
  258.     if ( TestBit(pPrint->printX[1], kHighResBit) )    //    High resolution; triple everything
  259.     {
  260.         if ( !TestBit(pPrint->printX[1], kResSetBit) )    //    App hasn't set imaging resolution
  261.         {
  262.             pPrint->prInfoPT.iHRes *= 3;
  263.             pPrint->prInfoPT.iVRes *= 3;
  264.             pPrint->prInfoPT.rPage.right *= 3;
  265.             pPrint->prInfoPT.rPage.bottom *= 3;
  266.         }
  267.         
  268.         pPrint->prXInfo.bPatScale = 3;         // Pattern triple ** NOT VALID QD ** Intercept in PrBand
  269.         pPrint->prInfoPT.iDev = 0xFD00;         // For QD's char spacing adjustment
  270.     }
  271.  
  272.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait mode
  273.     {
  274.         pPrint->prXInfo.iBandH = pPrint->prInfoPT.rPage.right;
  275.         pPrint->prXInfo.iBandV = 48;                                     // i8xBandScans = 24 * 2
  276.         iScans = pPrint->prInfoPT.rPage.bottom;
  277.         pPrint->prXInfo.scan = scanTop2Bottom;
  278.         iDevExtra = pPrint->prXInfo.iBandH;
  279.     }
  280.     else    //    Landscape mode
  281.     {
  282.         pPrint->prXInfo.iBandH = 48;                                     // i8xBandScans = 24 * 2;
  283.         pPrint->prXInfo.iBandV = pPrint->prInfoPT.rPage.bottom;
  284.         iScans = pPrint->prInfoPT.rPage.right;
  285.         pPrint->prXInfo.scan = scanLeft2Right;
  286.         iDevExtra = pPrint->prXInfo.iBandV;
  287.     }
  288.  
  289.     pPrint->prXInfo.iRowBytes = pPrint->prXInfo.iBandH >> 3;     // Must be even!
  290.     pPrint->prXInfo.iBands = ( iScans + 48 - 1 ) / 48;
  291.     
  292.     // Size a scan work buffer
  293.     pPrint->prXInfo.iDevBytes = ( pPrint->prXInfo.iRowBytes * pPrint->prXInfo.iBandV ) + ( iDevExtra * 3 ); 
  294.  
  295.     // Copy WDEV field back to old position for apps that read these flags
  296.     pPrint->prStl.wDev = pPrint->printX[1];
  297. }
  298. /* OldLQ_CiXMetrics */
  299.  
  300.  
  301. /****************************************************************************************
  302.  
  303.                             UpdatePrintRecord
  304.                             
  305.     function:
  306.                 This function updates the print record based upon the application's
  307.                 calls to PrGeneral.
  308.                 
  309.     parameters:                
  310.                 hPrint            print record to update
  311.                 
  312.     returns:
  313.                 none
  314.     
  315. ****************************************************************************************/
  316. void UpdatePrintRecord(THPrint hPrint)
  317. {
  318.     // emulate the old metric calculations        
  319.     OldLQ_CiMetrics(hPrint);
  320.     OldLQ_CiXMetrics(hPrint);
  321. }
  322. /* UpdatePrintRecord */
  323.  
  324.  
  325.  
  326. /***************************************************************************************
  327. *                                         INTERFACE ROUTINES                                                     *
  328. ***************************************************************************************/
  329.  
  330. /****************************************************************************************
  331.  
  332.                             SD_PrValidate
  333.                             
  334.     function:
  335.                 This function validates the print record.  If the passed-in print record contains
  336.                 valid information (see below), then it's updated based upon the application's
  337.                 calls to PrGeneral and the return code is true.
  338.                 Otherwise, the print record is defaulted (with PrintDefault), and the 
  339.                 return value is false.
  340.                 
  341.                 Validation:
  342.                     The upper byte of the PrintX[1] field must be the ID of the device 
  343.                         (kLQRefNum in OldAPIMessageIntf.h).
  344.                     
  345.                     The version of the print record must be current
  346.                         (oldIWLQPrintRecordVersion in Resources.h)
  347.                     
  348.                     (For new print records, we will validate all of the fields which are 
  349.                      public (e.g., paper size), not just these fields)
  350.                 
  351.     parameters:                
  352.                 hPrint                    print record to validate
  353.                 wasChanged                returns true if print record was invalid; false otherwise
  354.                 
  355.     returns:
  356.                 OSErr
  357.     
  358. ****************************************************************************************/
  359. OSErr SD_PrValidate(THPrint hPrint, Boolean *wasChanged)
  360. {
  361.     short        wDev;                        // device specific stuff in this word
  362.     Boolean    returnVal = true;        // initialize return value to "invalid"
  363.                                             //     Why is true == "invalid"? Nobody knows!
  364.     
  365.     // check the wDev.  The upper byte must be equal to kLQRefNum.  We get the
  366.     //  wDev, and shift wDev DOWN eight.
  367.         
  368.     wDev =  (*hPrint)->printX[1];
  369.     wDev >>= 8;                                // get just the device ID
  370.  
  371.  
  372.     // If the device id is equal, then check the version number of the print record.
  373.     //    Only if that is also equal to the current version, will we return false (valid).
  374.         
  375.     if (wDev == kLQRefNum)
  376.         if ( (*hPrint)->iPrVersion == oldIWLQPrintRecordVersion )
  377.             returnVal = false;
  378.             
  379.  
  380.     // If the print record is not valid, then return the default print record.
  381.     // Otherwise, update the print record, based on the application's calls
  382.     // to PrGeneral.
  383.  
  384.     if (returnVal)
  385.         PrintDefault(hPrint);
  386.     else
  387.         UpdatePrintRecord(hPrint);
  388.         
  389.     *wasChanged = returnVal;
  390.     
  391.     return(noErr);
  392. }
  393. /* SD_PrValidate */
  394.  
  395.  
  396. /****************************************************************************************
  397.  
  398.                             SD_ConvertPrintRecordTo
  399.                             
  400.     function:     
  401.                 SD_ConvertPrintRecordTo converts the fields of the print record for
  402.                 the device into the universal print record format.  
  403.                 
  404.     parameters:    
  405.                 hPrint        print record to convert to universal format
  406.     
  407.     returns:
  408.                 OSErr
  409.     
  410. ****************************************************************************************/
  411. OSErr SD_ConvertPrintRecordTo(THPrint hPrint)
  412. {
  413.     gxUniversalPrintRecordPtr    pUniv;
  414.     TPPrint                             pPrint;
  415.     short                                options = 0;
  416.  
  417.     pUniv = (gxUniversalPrintRecordPtr) *hPrint;
  418.     pPrint = *hPrint;
  419.     
  420.     // Convert paper feed settings (old and univ setting are switched)
  421.  
  422.     if ( pPrint->prStl.feed == oldPRECAutoFeed )
  423.         pUniv->feed = gxAutoFeed;
  424.     else
  425.         pUniv->feed = gxManualFeed;
  426.     
  427.     // Fix up the actualCopies field
  428.     pUniv->actualCopies = pPrint->prJob.iCopies;
  429.     
  430.     // Determine the new options field settings
  431.  
  432.     if ( TestBit(pPrint->prStl.wDev, kScrollBit) )
  433.         options |= gxBiggerPages;
  434.         
  435.     pUniv->options = options;
  436.  
  437.     
  438.     // Now determine the scaling factor, if any, and designate the proper dialog button that
  439.     // corresponds to the scaling factor.  The userCluster1 field specifies the dialog button.
  440.     
  441.     if ( TestBit(pPrint->prStl.wDev, k66PercentReducBit) )
  442.     {
  443.         pUniv->reduction = 66;
  444.         pUniv->userCluster1 = 1;
  445.     }
  446.     else 
  447.     if ( TestBit(pPrint->prStl.wDev, k33PercentReducBit) )
  448.     {
  449.         pUniv->reduction = 33;
  450.         pUniv->userCluster1 = 0;
  451.     }
  452.     else     //    T => No scaling being performed
  453.     {
  454.         pUniv->reduction = 100;
  455.         pUniv->userCluster1 = 2;
  456.     }
  457.     
  458.  
  459.     // Set the orientation properly
  460.  
  461.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )
  462.         pUniv->orientation = gxPortraitOrientation;
  463.     else
  464.         pUniv->orientation = gxLandscapeOrientation;
  465.  
  466.  
  467.     // Determine the quality setting
  468.     
  469.     if ( TestBit(pPrint->prStl.wDev, kHighResBit) )    //    T => Print in best quality
  470.     {
  471.         pUniv->qualityMode = gxBestQuality;
  472.     }
  473.     else
  474.     if ( pPrint->prJob.bJDocLoop == spool )    //    T => Print with faster quality
  475.     {
  476.         pUniv->qualityMode = gxFasterQuality;
  477.     }
  478.     else    //    T => Print with draft quality
  479.         pUniv->qualityMode = gxDraftQuality;
  480.     
  481.     
  482.     // Set the first tray and remaining tray fields
  483.     
  484.     if ( (pPrint->printX[0] & 0x0003) > 0 )    //    T => A first tray has been specified
  485.     {
  486.         switch ( pPrint->printX[0] & 0x0003 )
  487.         {
  488.             case    tray1:    pUniv->firstTray = gxFirstTray;        break;
  489.             case    tray2:    pUniv->firstTray = gxSecondTray;        break;
  490.             case    tray3:    pUniv->firstTray = gxThirdTray;        break;
  491.             default:            pUniv->firstTray = gxFirstTray;        break;
  492.         }
  493.     }
  494.     else
  495.         pUniv->firstTray = gxFirstTray;
  496.  
  497.     if ( (pPrint->printX[0] & 0x000C) > 0 )    //    T => A remaining tray has been specified
  498.     {
  499.         switch ( pPrint->printX[0] & 0x000C )
  500.         {
  501.             case    tray1:    pUniv->remainingTray = gxFirstTray;    break;
  502.             case    tray2:    pUniv->remainingTray = gxSecondTray;    break;
  503.             case    tray3:    pUniv->remainingTray = gxThirdTray;    break;
  504.             default:            pUniv->remainingTray = gxFirstTray;    break;
  505.         }
  506.     }
  507.     else
  508.         pUniv->remainingTray = gxFirstTray;
  509.  
  510.     
  511.     // Set the headMotion field's value
  512.     
  513.     if ( TestBit(pPrint->prStl.wDev, kBiDirBit) )    //    T => Print in bidirectional mode
  514.     {
  515.         pUniv->headMotion = gxBidirectionalMotion;
  516.     }
  517.     else
  518.         pUniv->headMotion = gxUnidirectionalMotion;
  519.  
  520.         
  521.     // Always assign these fields explicit values to ensure they don't cause problems
  522.     
  523.     pUniv->coverPage         = gxNoCoverPage;
  524.     pUniv->saveFile         = gxNoFile;
  525.     
  526.     return(noErr);
  527. }
  528. /* SD_ConvertPrintRecordTo */
  529.  
  530.  
  531. /****************************************************************************************
  532.  
  533.                             SD_ConvertPrintRecordFrom
  534.                             
  535.     function:     
  536.                 SD_ConvertPrintRecordFrom converts the fields of the print record in 
  537.                 universal print record format into the print record format for the
  538.                 specific device. 
  539.                 
  540.     parameters:    
  541.                 hPrint        print record to convert to device specific format
  542.     
  543.     returns:
  544.                 OSErr
  545.     
  546. ****************************************************************************************/
  547. OSErr SD_ConvertPrintRecordFrom(THPrint hPrint)
  548. {
  549.     gxUniversalPrintRecordPtr    pUniv;
  550.     TPPrint                             pPrint;
  551.     short                                newWDev = kLQRefNum << 8;
  552.  
  553.     pUniv = (gxUniversalPrintRecordPtr) *hPrint;
  554.     pPrint = *hPrint;
  555.     
  556.     // Convert paper feed settings (old and univ setting are switched)
  557.  
  558.     if ( pUniv->feed == gxAutoFeed )
  559.         pPrint->prStl.feed = oldPRECAutoFeed;
  560.     else
  561.         pPrint->prStl.feed = oldPRECManualFeed;
  562.  
  563.  
  564.     // Fix up the actualCopies field
  565.     pPrint->prJob.iCopies = pUniv->actualCopies;
  566.     
  567.     
  568.     // Determine the new wDev flag settings
  569.     
  570.     if ( TestBit(pUniv->options, gxBiggerPages) )
  571.         newWDev |= kScrollBit;
  572.         
  573.     if (pUniv->headMotion == gxBidirectionalMotion)
  574.         newWDev |= kBiDirBit;
  575.         
  576.     switch( pUniv->userCluster1 )    //    Based on the scaling dialog button setting, set the scaling factor
  577.     {
  578.         case 2:        //    Full size
  579.             break;
  580.             
  581.         case 1:
  582.             newWDev |= k66PercentReducBit;
  583.             break;
  584.             
  585.         case 0:
  586.             newWDev |= k33PercentReducBit;
  587.             break;
  588.     }
  589.     
  590.     if (pUniv->orientation == gxPortraitOrientation)
  591.         newWDev |= kPortraitBit;
  592.  
  593.     if (pUniv->qualityMode == gxBestQuality)
  594.     {
  595.         newWDev |= kHighResBit;
  596.         pPrint->prJob.bJDocLoop = spool;
  597.     }
  598.     else
  599.     if (pUniv->qualityMode == gxFasterQuality)
  600.     {
  601.         pPrint->prJob.bJDocLoop = spool;
  602.     }
  603.     else    //    T => Draft quality
  604.     {
  605.         newWDev |= kDraftBit;
  606.         pPrint->prJob.bJDocLoop = draft;
  607.     }
  608.  
  609.     // set the bit to indicate SetResolution has been called, if the resolution is already 216
  610.     if ( pPrint->prInfo.iVRes == 216)
  611.         newWDev |= kResSetBit;
  612.  
  613.     // Update the wDev field and the printX[1] field (a copy of wDev)
  614.     pPrint->prStl.wDev = newWDev;
  615.     pPrint->printX[1] = newWDev;
  616.     
  617.     
  618.     // Fix up the tray settings
  619.     {
  620.         short        firstTrayNum = tray1;
  621.         short        remainingTrayNum = tray1;
  622.         
  623.         switch (pUniv->firstTray)
  624.         {
  625.             case    gxFirstTray:        firstTrayNum = tray1;        break;
  626.             case    gxSecondTray:        firstTrayNum = tray2;        break;
  627.             case    gxThirdTray:        firstTrayNum = tray3;        break;
  628.         }
  629.         
  630.         switch (pUniv->remainingTray)
  631.         {
  632.             case    gxFirstTray:        remainingTrayNum = tray1;    break;
  633.             case    gxSecondTray:        remainingTrayNum = tray2;    break;
  634.             case    gxThirdTray:        remainingTrayNum = tray3;    break;
  635.         }
  636.         
  637.         pPrint->printX[0] = (remainingTrayNum << 2) | firstTrayNum;
  638.     }
  639.  
  640.     // Initialize some of the remaining fields in the TPrXInfo structure. PrValidate will fill in the rest
  641.     
  642.     pPrint->prXInfo.bUlThick = 0;
  643.     pPrint->prXInfo.bUlOffset = 0;
  644.     pPrint->prXInfo.bUlShadow = 0;
  645.     pPrint->prXInfo.bXInfoX = 0;
  646.  
  647.     return(noErr);
  648. }
  649. /* SD_ConvertPrintRecordFrom */
  650.  
  651.  
  652. /****************************************************************************************
  653.  
  654.                             SD_PrintRecordToJob
  655.                             
  656.     function:     
  657.                 SD_PrintRecordToJob is called by the Printing Manager when a print record
  658.                 needs to be converted into a job.  This driver takes this opportunity to
  659.                 add two collection items to the job, namely the one which specifies the
  660.                 desired head motion and the users tray selection.
  661.                 
  662.     parameters:    
  663.                 hPrint        print record to convert to a job
  664.                 theJob        job reference to use in converting the print record
  665.     
  666.     returns:
  667.                 OSErr
  668.     
  669. ****************************************************************************************/
  670. OSErr SD_PrintRecordToJob(THPrint hPrint, gxJob theJob)
  671. {
  672.     OSErr        anErr;
  673.     
  674.     // First forward the message so the job is created
  675.     anErr = Forward_GXPrintRecordToJob(hPrint, theJob);
  676.     require(anErr == noErr, Forward_GXPrintRecordToJob);
  677.     
  678.     // Add the collection item which specifies the desired head motion
  679.     {
  680.         HeadMotionJobItem        theMotion;
  681.         
  682.         theMotion.direction = (!TestBit((*hPrint)->prStl.wDev, kBiDirBit)) ? doUnidirectional : doBidirectional;
  683.         
  684.         anErr = AddCollectionItem(    GXGetJobCollection(theJob), 
  685.                                             kDrvrCreatorType, 
  686.                                             kHeadMotionItemIndex, 
  687.                                             sizeof(HeadMotionJobItem),
  688.                                             &theMotion);
  689.         require(anErr == noErr, AddHeadMotion);
  690.     }
  691.     
  692.     
  693.     // Add the collection item which specifies the desired tray settings
  694.     {
  695.         TraySettingsJobItem        theTraySettings;
  696.         
  697.         theTraySettings.firstPageFromTray = (*hPrint)->printX[0] & 0x0003;
  698.         theTraySettings.remainingFromTray = ((*hPrint)->printX[0] & 0x000C) >> 2;
  699.         
  700.         anErr = AddCollectionItem(    GXGetJobCollection(theJob), 
  701.                                             kDrvrCreatorType, 
  702.                                             kTraySettingsItemIndex, 
  703.                                             sizeof(TraySettingsJobItem),
  704.                                             &theTraySettings);
  705.         require(anErr == noErr, AddTraySettings);
  706.     }
  707.  
  708.  
  709. /******* Clean-up *******/
  710.  
  711. AddHeadMotion:
  712. AddTraySettings:
  713. Forward_GXPrintRecordToJob:
  714.     return(anErr);
  715. }
  716. /* SD_PrintRecordToJob */